{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import piplite\n",
    "\n",
    "await piplite.install([\"fixnotebook==0.2.1\", \"plotly==5.10.0\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Fix jupyter notebook\n",
    "\n",
    "Welcome to Fix!\n",
    "\n",
    "This is a showcase of how you can interact with fix using jupyter notebooks.\n",
    "\n",
    "Try running the cells below and explore the capabilities."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "After the installation, we need a few imports:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fixnotebook import FixNotebook"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The main interface is the `FixNotebook` class. It provides the methods to search the graph and visualize the results.\n",
    "\n",
    "To create the `FixNotebook` object, we need to pass the pre shared key (PSK). If you started the fixcore without the `--psk` option (e.g. in your local setup), you can pass None as the PSK: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "rnb = FixNotebook(\"\", psk=None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once we have the `FixNotebook` object, we can start performing searches.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Counting\n",
    "\n",
    "Get number of all collected instances by kind"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(await rnb.search(\"is(instance)\")).groupby([\"kind\"])[\"kind\"].count()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the cli command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "await rnb.cli_execute(\"search is(instance) | count kind\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Searching by kind\n",
    "\n",
    "Get list of all the DigitalOcean droplets:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "await rnb.search(\"is(digitalocean_droplet)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the cli command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "await rnb.cli_execute(\"search is(digitalocean_droplet)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Show the instances/cores/creation time heatmap:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import plotly.express as px\n",
    "\n",
    "data = await rnb.search(\"is(instance)\")\n",
    "px.density_heatmap(data, x=\"account_id\", y=\"instance_cores\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Selecting properties\n",
    "\n",
    "Get list of name, type, cores, and memory for each instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(await rnb.search(\"is(instance)\"))[[\"instance_type\", \"instance_cores\", \"instance_memory\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the cli command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "await rnb.cli_execute(\n",
    "    \"search is(instance) | list instance_type, instance_cores as cores, instance_memory as memory, /ancestors.account.reported.name as account\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Get a list of instance IDs and their creation times:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(await rnb.search(\"is(instance)\"))[[\"id\", \"ctime\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the cli command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "await rnb.cli_execute(\"search is(instance) | list id, ctime\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Filtering\n",
    "\n",
    "Get list of all compute instances with more than two CPU cores:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = await rnb.search(\"is(instance) and instance_cores > 2\")\n",
    "result[\"id\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Get list volumes that are not in use, larger than 10GB, older than 30 days. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(await rnb.search(\"is(volume) and volume_status != in-use and volume_size > 10 and age > 30d\"))[\"id\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Aggregation\n",
    "Count the number of instances by account ID:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = await rnb.search(\"is(instance)\")\n",
    "result.groupby([\"account_id\"])[\"account_id\"].count()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Aggregate RAM usage (bytes) data grouped by cloud, region, and instance type:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = await rnb.search(\"is(instance) and instance_status == running\")\n",
    "result.groupby([\"cloud_id\", \"region_id\", \"instance_type\"], as_index=False)[[\"instance_cores\"]].sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the cli:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"\"\"\n",
    "search is(instance) and instance_status == running | aggregate\n",
    "  /ancestors.cloud.reported.name as cloud,\n",
    "  /ancestors.region.reported.name as region,\n",
    "  instance_type as type: sum(instance_memory) as memory_bytes\n",
    "  \"\"\"\n",
    "await rnb.cli_execute(query)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.6 ('venv': venv)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "4c2078171d0cd0ffabd8b3545d2f0a210aefc84007d21792c1d0ad5c88643a71"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
